package com.autonavi.yunda.yunji.core.utils.datahub;

import com.alibaba.security.SecurityUtil;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Setter
@Getter
public class Condition {
    private String relation;
    private List<Condition> conditions;
    private String field;
    private String operation;
    private Object value;

    /**
     * 合并两个propetties筛选条件json
     *
     * @param properties   原条件
     * @param extendFilter 数据集继承条件
     * @return and合并后的条件
     */
    public static Map<String, Object> mergeConditions(Map<String, Object> properties, Map<String, Object> extendFilter) {
        Map<String, Object> mergedFilter = new HashMap<>();
        if (properties != null && extendFilter != null) {
            mergedFilter.put("relation", "and");
            mergedFilter.put("conditions", Stream.of(properties, extendFilter).collect(Collectors.toList()));
        } else {
            mergedFilter = properties == null ? extendFilter : properties;
        }
        return mergedFilter;
    }

    public String translateToSql() {
        return translateToSql("");
    }

    /**
     * @param jsonColName 指定json列名称
     * @return
     */
    public String translateToSql(String jsonColName) {
        if (relation != null && conditions != null) {
            List<String> cons = new ArrayList<>();
            for (Condition co : conditions) {
                if (co.getRelation() != null && co.getConditions() != null) {
                    if (StringUtils.isNotEmpty(co.translateToSql(jsonColName))) {
                        cons.add(co.translateToSql(jsonColName));
                    }
                } else if (co.getField() != null && co.getOperation() != null) {
                    if (StringUtils.isNotEmpty(co.translateOperation(jsonColName))) {
                        cons.add(co.translateOperation(jsonColName));
                    }
                } else if (co.getField() == null && co.getOperation() != null && field != null) {
                    //使用父级的field
                    co.setField(field);
                    if (StringUtils.isNotEmpty(co.translateOperation(jsonColName))) {
                        cons.add(co.translateOperation(jsonColName));
                    }
                }
            }
            if (cons.isEmpty()) {
                return "";
            }
            String s = cons.stream().reduce((str1, str2) -> str1 + " " + SqlOperator.translateToSql(relation) + " " + str2).orElse("");
            return "( " + s + " )";
        }

        return "";
    }

    private String translateOperation() {
        return translateOperation("");
    }

    private String translateOperation(String jsonColName) {
        if (StringUtils.isBlank(jsonColName)) {
            jsonColName = "properties";
        }
        SqlOperator operator = SqlOperator.judge(this.getOperation());
        if (operator == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append("(");
        sb.append("(").append(jsonColName).append(" ->> '");
        sb.append(SecurityUtil.escapeSql(this.getField()));
        sb.append("')");
        if (operator.isNumberic()) {
            sb.append("::numeric");
        }
        sb.append(" ");
        if (this.getValue() != null) {
            switch (operator) {
                case in:
                    sb.append(operator.getSql());
                    String listvalue = this.getValue().toString();
                    String[] split = StringUtils.split(listvalue, '|');
                    List<String> keywords = new ArrayList<>();
                    for (String s : split) {
                        keywords.add(" '" + SecurityUtil.escapeSql(s) + "' ");
                    }
                    String join = StringUtils.join(keywords, ",");
                    sb.append(" (");
                    sb.append(join);
                    sb.append(") ");
                    break;
                case start_with:
                    sb.append(operator.getSql());
                    sb.append(" '");
                    sb.append(replaceWildcardForLike());
                    sb.append("%");
                    sb.append("' ");
                    break;
                default:
                    sb.append(operator.getSql());
                    sb.append(" '");
                    if (operator.needPercent()) {
                        sb.append("%");
                    }
                    sb.append(replaceWildcardForLike());
                    if (operator.needPercent()) {
                        sb.append("%");
                    }
                    sb.append("' ");
            }

        } else {
            //处理null
            switch (operator) {
                case equal:
                case equal_:
                    sb.append("is");
                    break;
                case not_equal:
                case not_equal_:
                    sb.append("is not");
                    break;
                default:
                    return "";
            }
            sb.append(" ");
            sb.append("null");
            sb.append(" ");
        }
        sb.append(")");
        return sb.toString();
    }

    private String replaceWildcardForLike() {
        return StringUtils.replaceEach(SecurityUtil.escapeSql(this.getValue().toString()), new String[]{"_", "%"}, new String[]{"\\_", "\\%"});
    }

    public enum Relation {

        /**
         * 且
         */
        AND("and", "且"),

        /**
         * 或
         */
        OR("or", "或");
        private final String code;
        private final String meaning;

        Relation(String code, String meaning) {
            this.code = code;
            this.meaning = meaning;
        }

        public String getCode() {
            return code;
        }

        public String getMeaning() {
            return meaning;
        }
    }
}
